<template>
  <div v-transfer-dom>
    <transition :name="transitionNames[1]">
      <div :class="maskClasses" v-show="visible" @click="mask"></div>
    </transition>
    <div :class="wrapClasses" @click="handleWrapClick">
      <transition :name="transitionNames[0]">
        <div :class="classes" :style="mainStyles" v-show="visible">
          <div :class="[prefixCls + '-content']">
            <a :class="[prefixCls + '-close']" v-if="closable" @click="close">
              <slot name="close">
                <oolongIcon type="ios-close-empty"></oolongIcon>
              </slot>
            </a>
            <div :class="[prefixCls + '-header']" v-if="showHead">
              <slot name="header">
                <div
                  :class="[prefixCls + '-header-inner']">{{ title }}
                </div>
              </slot>
            </div>
            <div :class="[prefixCls + '-body']">
              <slot></slot>
            </div>
            <div :class="[prefixCls + '-footer']" v-if="!footerHide">
              <slot name="footer">
                <oolongButton type="text" size="large" @click.native="cancel">{{ localeCancelText
                  }}
                </oolongButton>
                <oolongButton type="primary" size="large" :loading="buttonLoading"
                              @click.native="ok">{{ localeOkText }}
                </oolongButton>
              </slot>
            </div>
          </div>
        </div>
      </transition>
    </div>
  </div>
</template>
<script>
  import oolongIcon from '../icon';
  import oolongButton from '../button';
  import TransferDom from '../../directives/transfer-dom';
  import {getScrollBarSize} from '../../utils/assist';
  import Locale from '../../mixins/locale';
  import Emitter from '../../mixins/emitter';

  const prefixCls = 'oolong-modal';

  export default {
    name: 'oolongDialong',
    mixins: [Locale, Emitter],
    components: {oolongIcon, oolongButton},
    directives: {TransferDom},
    props: {
      value: {
        type: Boolean,
        default: false
      },
      closable: {
        type: Boolean,
        default: true
      },
      maskClosable: {
        type: Boolean,
        default: true
      },
      title: {
        type: String
      },
      width: {
        type: [Number, String],
        default: 520
      },
      okText: {
        type: String
      },
      cancelText: {
        type: String
      },
      loading: {
        type: Boolean,
        default: false
      },
      styles: {
        type: Object
      },
      className: {
        type: String
      },
      // for instance
      footerHide: {
        type: Boolean,
        default: false
      },
      scrollable: {
        type: Boolean,
        default: false
      },
      transitionNames: {
        type: Array,
        default () {
          return ['ease', 'fade'];
        }
      }
    },
    data () {
      return {
        prefixCls: prefixCls,
        wrapShow: false,
        showHead: true,
        buttonLoading: false,
        visible: this.value
      };
    },
    computed: {
      wrapClasses () {
        return [
          `${prefixCls}-wrap`,
          {
            [`${prefixCls}-hidden`]: !this.wrapShow,
            [`${this.className}`]: !!this.className
          }
        ];
      },
      maskClasses () {
        return `${prefixCls}-mask`;
      },
      classes () {
        return `${prefixCls}`;
      },
      mainStyles () {
        let style = {};

        const styleWidth = {
          width: `${this.width}px`
        };

        const customStyle = this.styles ? this.styles : {};

        Object.assign(style, styleWidth, customStyle);

        return style;
      },
      localeOkText () {
        if (this.okText === undefined) {
          return this.t('i.modal.okText');
        } else {
          return this.okText;
        }
      },
      localeCancelText () {
        if (this.cancelText === undefined) {
          return this.t('i.modal.cancelText');
        } else {
          return this.cancelText;
        }
      }
    },
    methods: {
      close () {
        this.visible = false;
        this.$emit('input', false);
        this.$emit('on-cancel');
      },
      mask () {
        if (this.maskClosable) {
          this.close();
        }
      },
      handleWrapClick (event) {
        // use indexOf,do not use === ,because ivu-modal-wrap can have other custom className
        const className = event.target.getAttribute('class');
        if (className && className.indexOf(`${prefixCls}-wrap`) > -1) this.mask();
      },
      cancel () {
        this.close();
      },
      ok () {
        if (this.loading) {
          this.buttonLoading = true;
        } else {
          this.visible = false;
          this.$emit('input', false);
        }
        this.$emit('on-ok');
      },
      EscClose (e) {
        if (this.visible && this.closable) {
          if (e.keyCode === 27) {
            this.close();
          }
        }
      },
      checkScrollBar () {
        let fullWindowWidth = window.innerWidth;
        if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8
          const documentElementRect = document.documentElement.getBoundingClientRect();
          fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left);
        }
        this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth;
        if (this.bodyIsOverflowing) {
          this.scrollBarWidth = getScrollBarSize();
        }
      },
      setScrollBar () {
        if (this.bodyIsOverflowing && this.scrollBarWidth !== undefined) {
          document.body.style.paddingRight = `${this.scrollBarWidth}px`;
        }
      },
      resetScrollBar () {
        document.body.style.paddingRight = '';
      },
      addScrollEffect () {
        this.checkScrollBar();
        this.setScrollBar();
        document.body.style.overflow = 'hidden';
      },
      removeScrollEffect() {
        document.body.style.overflow = '';
        this.resetScrollBar();
      }
    },
    mounted () {
      if (this.visible) {
        this.wrapShow = true;
      }

      let showHead = true;

      if (this.$slots.header === undefined && !this.title) {
        showHead = false;
      }

      this.showHead = showHead;

      // ESC close
      document.addEventListener('keydown', this.EscClose);
    },
    beforeDestroy () {
      document.removeEventListener('keydown', this.EscClose);
      this.removeScrollEffect();
    },
    watch: {
      value (val) {
        this.visible = val;
      },
      visible (val) {
        if (val === false) {
          this.buttonLoading = false;
          this.timer = setTimeout(() => {
            this.wrapShow = false;
            this.removeScrollEffect();
          }, 300);
        } else {
          if (this.timer) clearTimeout(this.timer);
          this.wrapShow = true;
          if (!this.scrollable) {
            this.addScrollEffect();
          }
        }
        this.broadcast('Table', 'on-visible-change', val);
      },
      loading (val) {
        if (!val) {
          this.buttonLoading = false;
        }
      },
      scrollable (val) {
        if (!val) {
          this.addScrollEffect();
        } else {
          this.removeScrollEffect();
        }
      },
      title (val) {
        if (this.$slots.header === undefined) {
          this.showHead = !!val;
        }
      }
    }
  };
</script>
